using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
using SpoonCore.Message;

namespace SpoonCore.Handler.Core
{
	internal class PingManager
	{
		public const int Timeout = 2;

		public delegate void OnPingTimeoutHandler(ClientInfo client);

		public event OnPingTimeoutHandler OnPingTimeout;

		private SpoonClient _client;
		private Timer _timer = new Timer(1000);
		private SortedList<int, PingItem> _pingList = new SortedList<int, PingItem>();

		public PingManager(SpoonClient client)
		{
			_client = client;

			OnPingTimeout += new OnPingTimeoutHandler(client.RemoveClient);

			_timer.Elapsed += new ElapsedEventHandler(TimerElapsed);
			_timer.Start();
		}

		private void TimerElapsed(object sender, ElapsedEventArgs e)
		{
			// create new ping for all leave nodes
			foreach (ClientInfo client in _client.LeaveTable.Clients)
			{
				PingMessage msg = new PingMessage();
				lock (_pingList)
				{
					_pingList.Add(msg.Id, new PingItem(msg, client));
				}
				client.Send(msg);
			}

			// remove TimeoutMessage
			lock (_pingList)
			{
				for (int x = 0; x < _pingList.Values.Count; x++)
				{
					if (_pingList.Values[x].Message.Time.AddSeconds(Timeout) < DateTime.Now)
					{
						Console.WriteLine("Timeout for " + _pingList.Values[x].Client.Id);
						if (OnPingTimeout != null) OnPingTimeout(_pingList.Values[x].Client);
						_pingList.RemoveAt(x);
						x--;
					}
				}
			}
		}

		public void ReceivePing(PingMessage msg)
		{
			lock (_pingList)
			{
				if (_pingList.ContainsKey(msg.Id))
				{
					//Console.WriteLine("Answer in " + (DateTime.Now - _pingList[msg.Id].Message.Time).TotalMilliseconds + "ms");
					_pingList.Remove(msg.Id);
				}
			}
		}

		internal class PingItem
		{
			public PingMessage Message;
			public ClientInfo Client;

			public PingItem(PingMessage msg, ClientInfo client)
			{
				Message = msg;
				Client = client;
			}
		}
	}
}